package edu.uestc.gene.test;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;

public class RandomGen {
	// 利用HashSet的特征，只能存放不同的值
	public static HashSet<Integer> set = new HashSet<Integer>();
	public int count;// 需要生成随机数的个数

	public RandomGen(int num) {
		this.count = num;
	}

	public static RandomGen init(int num) {
		set.clear();
		return new RandomGen(num);
	}

	// 生成【begin，end】区间内num个随机数
	public void genRadoms(int begin, int end, int num, HashSet<Integer> set) {
		if (num > (end - begin + 1) || end < begin) {
			return;
		}
		for (int i = 0; i < num; i++) {// 生成num个随机数
			// 调用Math.random()方法
			int temp = (int) (Math.random() * (end - begin)) + begin;
			set.add(temp);// 将不同的数存入HashSet中
		}
		int setLen = set.size();
		// 如果存入的数小于指定生成的个数，则调用递归再生成剩余个数的随机数，如此循环，直到达到指定大小
		if (setLen < count) {
			genRadoms(begin, end, count - setLen, set);// 递归
		}
	}

	public static void printSet(HashSet<Integer> set) {// 打印结果
		int count = 1;
		Iterator<Integer> i = set.iterator();
		while (i.hasNext()) {
			System.out.print("[" + count + "]:" + i.next() + " ");
			if (count % 10 == 0) {
				System.out.println();
			}
			count++;
		}
	}

	// 下面是网上的几种方法：

	// 使用一个临时数组，通过不断减小生成的数组索引实现：
	public static int[] noRepRandoms() {
		int[] tmpArray = new int[10];
		for (int i = 0; i < tmpArray.length; i++)
			tmpArray[i] = i;
		int[] results = new int[10];
		Random rd = new Random();
		int tmpIndex = 0, len = tmpArray.length;
		for (int i = results.length - 1; i >= 0; i--) {
			tmpIndex = Math.abs(rd.nextInt() % len);
			len--;
			results[i] = tmpArray[tmpIndex];
			tmpArray[tmpIndex] = tmpArray[len];
		}
		return results;
	}

	// 第一种方法，在一个待选数组中随机产生一个数，然后把他放到待选数组的最后，然后从length-1里随机产生下一个随机数，如此类推

	public static int[] randoms() {
		Random r = new Random();

		int temp1, temp2;
		int send[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
				16, 17, 18, 19, 20, 21 };
		int len = send.length;
		int returnValue[] = new int[22];
		for (int i = 0; i < 22; i++) {
			temp1 = Math.abs(r.nextInt()) % len;
			returnValue[i] = send[temp1];
			temp2 = send[temp1];
			send[temp1] = send[len - 1];
			send[len - 1] = temp2;
			len--;
		}
		return returnValue;
	}

	// 方法二：还是一个固定的无重复的数组，然后把这个数组随机调换位置，多次之后这个数组就是一个无重复的随机数组了。

	public static int[] random2() {
		int send[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
				16, 17, 18, 19, 20, 21 };
		int temp1, temp2, temp3;
		Random r = new Random();
		for (int i = 0; i < send.length; i++) // 随机交换send.length次
		{
			temp1 = Math.abs(r.nextInt()) % (send.length - 1); // 随机产生一个位置
			temp2 = Math.abs(r.nextInt()) % (send.length - 1); // 随机产生另一个位置
			if (temp1 != temp2) {
				temp3 = send[temp1];
				send[temp1] = send[temp2];
				send[temp2] = temp3;
			}
		}
		return send;
	}

	public static void main(String[] args) {
		RandomGen.init(80).genRadoms(10, 100, 80, set);
		RandomGen.printSet(set);
	}
}